package com.huarui.companypackage.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.ewaf.framework.service.BaseService;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;

import com.huarui.company.dao.ICompanyDao;
import com.huarui.company.model.Company;
import com.huarui.company.model.CompanyMarket;
import com.huarui.companydeal.dao.ICompanyDealDao;
import com.huarui.companydeal.model.CompanyDeal;
import com.huarui.companypackage.dao.IBuyPackageDao;
import com.huarui.companypackage.dao.IBuyPackageItemDao;
import com.huarui.companypackage.dao.ICompanyMarketDao;
import com.huarui.companypackage.dao.ICompanyPackageServiceDao;
import com.huarui.companypackage.dao.IPackageCompanyTypeDao;
import com.huarui.companypackage.dao.IPackageDao;
import com.huarui.companypackage.dao.IServiceDao;
import com.huarui.companypackage.model.BuyPackage;
import com.huarui.companypackage.model.BuyPackageItem;
import com.huarui.companypackage.model.Package;
import com.huarui.companypackage.model.CompanyPackageService;
import com.huarui.companypackage.model.PackageCompanyType;
import com.huarui.companypackage.model.Service;
import com.huarui.companypackage.util.CompanyPackageConstant;
import com.huarui.dictionary.DictionaryEnum;
import com.huarui.dictionary.service.DictionaryReadOnlyService.DictionaryResource;
import com.huarui.market.dao.IMarketDao;
import com.huarui.market.model.Market;
import com.huarui.permission.service.PermissionService;
import com.huarui.quotation.service.QuotationService;
import com.huarui.user.model.SessionMessage;
import com.huarui.user.security.UserHolder;
import com.huarui.util.DateParseUtil;
/**
 * 套餐
 * @author yi
 *
 */
public class PackageService extends BaseService {

	private IServiceDao serviceDao;
	private ICompanyPackageServiceDao companyPackageServiceDao;
	private IPackageCompanyTypeDao packageCompanyTypeDao;
	private IPackageDao getDao(){
		return (IPackageDao) dao;
	}
	private ICompanyDao companyDao;
	private IBuyPackageDao buyPackageDao;
	private IBuyPackageItemDao buyPackageItemDao;
	private ICompanyMarketDao companyMarketDao;
	private IMarketDao marketDao;
	private PermissionService permissionService;
	private DealCompanyMarketByCompanyTypeFactory dealCompanyMarketByCompanyTypeFactory;
	private ICompanyDealDao companyDealDao;


	/**
	 * 增加套餐,保存package,packageService,packageCompanyType
	 * @param queryParam
	 */
	public void createPackage(String queryParam) {
		JSONObject queryObject = JSONObject.fromObject(queryParam);
		final Package companyPackage = (Package) JSONObject.toBean(queryObject, Package.class);
		final List<String> serviceIds = companyPackage.getServiceIds();
		final List<String> companyTypes = companyPackage.getCompanyTypes();
		transactionTemplate.execute(new TransactionCallback() {			
			@Override
			public Object doInTransaction(TransactionStatus status) {
				getDao().create(companyPackage);
				List<CompanyPackageService> packageServices = generateCompanyPackageService(companyPackage,serviceIds);
				List<PackageCompanyType> packageCompanyTypes = generatePackageCompanyType(companyPackage,companyTypes);
				companyPackageServiceDao.batchInsertPackageService(packageServices);
				packageCompanyTypeDao.batchInsertPackageCompanyType(packageCompanyTypes);
				return status;
			}
		});
	}
	/**
	 * 根据公司类型查询相关套餐
	 * @param companyType 公司类型
	 * @param isGift 是否查询免费套餐
	 * @return
	 */
	public List<Package> getPackagesByCompanyType(Integer companyType,Integer isGift) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		map.put("companyType", companyType);
		map.put("isGift", isGift);
		return getDao().getPackagesByCompanyType(map);
	}
	/**
	 * 查询所有套餐
	 * @param jsonResult 
	 * @return
	 */
	public Map<String,Object> getAllPackages(Map<String, Object> jsonResult) {
		int count = getDao().count();
		List<Package> packages = getDao().getAllPackages(jsonResult);
		jsonResult.clear();
		jsonResult.put("totalProperty", count);
		jsonResult.put("root", packages);
		return jsonResult;
	}


	private List<PackageCompanyType> generatePackageCompanyType(Package companyPackage, List<String> companyTypes) {
		List<PackageCompanyType> packageCompanyTypes = new ArrayList<PackageCompanyType>();
		for(String companyType :companyTypes){
			PackageCompanyType packageCompanyType = new PackageCompanyType();
			packageCompanyType.setPackageId(companyPackage.getId());
			packageCompanyType.setCompanyType(Integer.valueOf(companyType));
			packageCompanyTypes.add(packageCompanyType);
		}
		return packageCompanyTypes;
	}

	private List<CompanyPackageService> generateCompanyPackageService(Package companyPackage, List<String> serviceIds) {
		List<CompanyPackageService> packageServices = new ArrayList<CompanyPackageService>();
		for(String serviceId : serviceIds){
			CompanyPackageService packageService = new CompanyPackageService();
			Service service = serviceDao.getServiceById(Integer.valueOf(serviceId));
			packageService.setPackageId(companyPackage.getId());
			packageService.setServiceId(Integer.valueOf(serviceId));
			packageService.setServiceCode(service.getCode());
			packageService.setServiceName(service.getName());
			packageService.setDuration(DateParseUtil.monthsBetween(DateParseUtil.format(companyPackage.getGmtBegin()),DateParseUtil.format(companyPackage.getGmtEnd())));
			packageServices.add(packageService);
		}
		return packageServices;
	}

	@SuppressWarnings("unchecked")
	public Map<String,Object> buyPackage(String queryParam,final String ip) {
		JSONObject paramObject = JSONObject.fromObject(queryParam);	
		List<String> marketIds = null;		
		if(paramObject.containsKey(CompanyPackageConstant.MARKETIDS.getType())){
			marketIds = (List<String>) JSONArray.toCollection(paramObject.getJSONArray(CompanyPackageConstant.MARKETIDS.getType()),String.class);
		}
		final Integer packageId = paramObject.getInt(CompanyPackageConstant.PACKAGEID.getType());
		final Package compPackage = (Package) getDao().getById(packageId);
		//套餐有效时长(天)
		final int duration = DateParseUtil.daysBetween(DateParseUtil.format(compPackage.getGmtBegin()),DateParseUtil.format(compPackage.getGmtEnd()));
		//查询用户账户余额
		final SessionMessage sessionMessage = UserHolder.getCurrentSessionMessage();
		final Integer companyId = sessionMessage.getCompanyId();		
		final List<String> mIds = marketIds;
		Map<String,Object> result = (Map) transactionTemplate.execute(new TransactionCallback() {			
			@Override
			public Object doInTransaction(TransactionStatus status) {
			    Company company = companyDao.getCompanyByIdForUpdate(companyId);
				Map<String,Object> map = new HashMap<String, Object>();
			    BigDecimal newBalance = company.getBalance().subtract(compPackage.getPrice());
				if(newBalance.doubleValue()< 0 ){
					//账户余额不足
					map.put("success", false);
					map.put(CompanyPackageConstant.MSG.getType(), CompanyPackageConstant.NO_SAVE_ACCOUNT.getType());
					return map;
				}
				//保存buyPackage
				BuyPackage buyPackage = createPackage(compPackage, companyId);
				//保存BuyPackageItem
				createBuyPackageItem(mIds, buyPackage);				
				//保存companyDeal,交易记录
				createCompanyDeal(ip, compPackage, sessionMessage, company,buyPackage);		
				//保存companyMarket
				CompanyMarketByCompanyTypeService cms = dealCompanyMarketByCompanyTypeFactory.getBean(sessionMessage.getCompanyType());
				Map<String,List<CompanyMarket>> cmMap = cms.getCompanyMarket4CompanyByType(mIds, duration,company.getMarketId());
				List<CompanyMarket> companyAddedMarkets = cmMap.get(CompanyPackageConstant.COMPANYADDEDMARKETS.getType());				
				if(!companyAddedMarkets.isEmpty()){
					companyMarketDao.batchInsertCompanyMarket(companyAddedMarkets);
				}
				List<CompanyMarket> companyUpdateMarkets = cmMap.get(CompanyPackageConstant.COMPANYUPDATEMARKETS.getType());	
				if(!companyUpdateMarkets.isEmpty()){
					companyMarketDao.batchUpdateCompanyMarket(companyUpdateMarkets);
				}
				//分配权限角色
				permissionService.assignPackage2AuthCompany(companyId, packageId);
				company.setBalance(newBalance);
				company.setPaid(Company.PAID_YES);
				companyDao.updateCompany(company);				
				map.put("success", true);
				map.put("msg", "购买套餐成功!");
				
				return map;
			}

			
		});
		return result;
		
	}
	
	private void createCompanyDeal(String ip,Package compPackage,SessionMessage sessionMessage,Company company,BuyPackage buyPackage) {
		CompanyDeal companyDeal = new CompanyDeal();
		companyDeal.setCompanyId(company.getId());
		companyDeal.setIp(ip);
		companyDeal.setCreatorId(sessionMessage.getUserId());
		companyDeal.setCreatorName(sessionMessage.getUserName());
		companyDeal.setBorrow(compPackage.getPrice());
		companyDeal.setLoan(BigDecimal.ZERO);
		companyDeal.setBeginBalance(company.getBalance());
		companyDeal.setEndBalance((companyDeal.getBeginBalance().subtract(companyDeal.getBorrow())));
		companyDeal.setDealType(CompanyDeal.DEALTYPE_BUYPACKAGE);
		companyDeal.setDealId(buyPackage.getId());
		companyDeal.setDealName(DictionaryResource.getDictionaryValue(DictionaryEnum.GROUP_COMPANYDEAL_DEALTYPE, String.valueOf(CompanyDeal.DEALTYPE_BUYPACKAGE)));
		companyDealDao.create(companyDeal);
	}
	
	private BuyPackage createPackage(Package compPackage,Integer companyId) {
		BuyPackage buyPackage = new BuyPackage();
		buyPackage.setCode(compPackage.getCode());
		buyPackage.setCompanyId(companyId);
		buyPackage.setPackageId(compPackage.getId());
		buyPackage.setStatus(BuyPackage.HAS_PAID);
		buyPackageDao.create(buyPackage);
		return buyPackage;
	}
	
	private void createBuyPackageItem(final List<String> mIds,BuyPackage buyPackage) {
		List<BuyPackageItem> buyPackageItems = new ArrayList<BuyPackageItem>();				
		if (mIds != null) {
			for (String marketId : mIds) {
				Market market = (Market) marketDao.getById(Integer.valueOf(marketId));
				BuyPackageItem buyPackageItem = new BuyPackageItem();
				buyPackageItem.setBuyPackageId(buyPackage.getId());
				buyPackageItem.setItemName(market.getName());
				buyPackageItem.setItemValue(market.getId());
				buyPackageItem.setItemDescription(market.getDescription());
				buyPackageItems.add(buyPackageItem);
			}
			buyPackageItemDao.batchInsertBuyPackageItem(buyPackageItems);
		}		
	}
	
	public void setCompanyDao(ICompanyDao companyDao) {
		this.companyDao = companyDao;
	}

	public void setServiceDao(IServiceDao serviceDao) {
		this.serviceDao = serviceDao;
	}

	public void setCompanyPackageServiceDao(ICompanyPackageServiceDao companyPackageServiceDao) {
		this.companyPackageServiceDao = companyPackageServiceDao;
	}

	public void setPackageCompanyTypeDao(IPackageCompanyTypeDao packageCompanyTypeDao) {
		this.packageCompanyTypeDao = packageCompanyTypeDao;
	}
	public void setBuyPackageDao(IBuyPackageDao buyPackageDao) {
		this.buyPackageDao = buyPackageDao;
	}
	public void setMarketDao(IMarketDao marketDao) {
		this.marketDao = marketDao;
	}
	public void setBuyPackageItemDao(IBuyPackageItemDao buyPackageItemDao) {
		this.buyPackageItemDao = buyPackageItemDao;
	}
	public void setCompanyMarketDao(ICompanyMarketDao companyMarketDao) {
		this.companyMarketDao = companyMarketDao;
	}
	public void setPermissionService(PermissionService permissionService) {
		this.permissionService = permissionService;
	}
	public void setDealCompanyMarketByCompanyTypeFactory(
			DealCompanyMarketByCompanyTypeFactory dealCompanyMarketByCompanyTypeFactory) {
		this.dealCompanyMarketByCompanyTypeFactory = dealCompanyMarketByCompanyTypeFactory;
	}
	public void setCompanyDealDao(ICompanyDealDao companyDealDao) {
		this.companyDealDao = companyDealDao;
	}
	
	
	
}
